package com.example.demo.controller;

import cn.hutool.core.util.StrUtil;
import com.example.demo.annotation.Log;
import com.example.demo.annotation.RequestAuthCheck;
import com.example.demo.config.ConstantConfig;
import com.example.demo.entity.BaseEntity;
import com.example.demo.entity.Menu;
import com.example.demo.entity.Role;
import com.example.demo.entity.User;
import com.example.demo.entity.dto.GiveRolesDto;
import com.example.demo.entity.dto.LoginDto;
import com.example.demo.entity.dto.PageDto;
import com.example.demo.entity.vo.*;
import com.example.demo.enums.StatusCodeEnum;
import com.example.demo.enums.log.BusinessTypeEnum;
import com.example.demo.enums.log.OperatorTypeEnum;
import com.example.demo.exception.CustomException;
import com.example.demo.service.TestAsyncTaskService;
import com.example.demo.service.UserService;
import com.example.demo.util.*;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @description：用户相关接口的控制器.
 * @author：lw
 * @since：2023/12/27
 **/

@Tag(name="用户接口")
@ApiSupport(order = 1)
@RestController
@RequestMapping(value = "/admin/user")
public class UserController {

    @Autowired
    UserService userService;

    @Autowired
    TestAsyncTaskService testAsyncTaskService;

    @Autowired
    ResourceLoader resourceLoader;


    private final String menuName="user";


    @Operation(summary = "测试")
    @ApiOperationSupport(order = 1 ,author = "lw")
//    @Parameters({
//            @Parameter(name = "name",description = "名称",required = true,in= ParameterIn.PATH)
//    })
    @GetMapping(value = "/test")
    public ResponseResult<Object> test(String msg) {
//        String  _msg=RsaUtil.decrypt(msg);
        String  _msg=AesUtil.decrypt(msg);
        return  ResponseResult.build(_msg,StatusCodeEnum.success);
    };

    @Operation(summary = "新增")
    @ApiOperationSupport(order = 2,author = "lw")
    @RequestAuthCheck(menuName = menuName,action = ConstantConfig.add)   // 鉴权注解最好写上面，已达到没权限就不执行其他
    @Log(title = "新增用户",businessType = BusinessTypeEnum.add,operatorType = OperatorTypeEnum.admin_user)
    @PostMapping(value = "/add")
    public ResponseResult<Boolean> add(@RequestBody List<User> list) {
//        return  ResponseResult.build(userService.save(user),StatusCodeEnum.add_success);
        return  ResponseResult.build(userService.saveBatch(list),StatusCodeEnum.add_success);
    }


    @Operation(summary = "删除")
    @ApiOperationSupport(order = 3 ,author = "lw")
    @RequestAuthCheck(menuName = menuName,action = ConstantConfig.delete)
    @Log(title = "删除用户",businessType = BusinessTypeEnum.delete,operatorType = OperatorTypeEnum.admin_user)
    @PostMapping(value = "/deleteByIds")
    public ResponseResult<Boolean> deleteByIds(@RequestBody List<Long> ids) {
//        UpdateWrapper<User> updateWrapper=new UpdateWrapper<>();
//        updateWrapper.in("id",ids);
//        updateWrapper.set("is_deleted",1);
//        return  ResponseResult.build(userService.update(updateWrapper),StatusCodeEnum.delete_success);
        return  ResponseResult.build(userService.removeByIds(ids),StatusCodeEnum.delete_success);
    }

    @Operation(summary = "更新")
    @ApiOperationSupport(order = 4 ,author = "lw")
    @RequestAuthCheck(menuName = menuName,action = ConstantConfig.update)
    @Log(title = "更新用户",businessType = BusinessTypeEnum.update,operatorType = OperatorTypeEnum.admin_user)
    @PostMapping(value = "/update")
    public ResponseResult<Boolean> update(@RequestBody List<User> list) {
//        return  ResponseResult.build(userService.updateById(user),StatusCodeEnum.update_success);
        list.forEach(v->{
            // 敏感字段处理
            if(StrUtil.isBlank(v.getWxOpenid()) || StrUtil.isBlank(v.getPassword()) || StrUtil.isBlank(v.getPhone())) {
                User user=userService.getById(v.getId());
                if(user==null) throw new CustomException(StatusCodeEnum.update_fail);
                else  {
                    if(StrUtil.isBlank(v.getPassword())) v.setPassword(user.getPassword());
                    if(StrUtil.isBlank(v.getPhone())) v.setPhone(user.getPhone());
                    if(StrUtil.isBlank(v.getWxOpenid())) v.setWxOpenid(user.getWxOpenid());
                }
            }
        });
        return  ResponseResult.build(userService.updateBatchById(list),StatusCodeEnum.update_success);
    }

    @Operation(summary = "列表查询")
    @ApiOperationSupport(order = 5 ,author = "lw")
    @PostMapping(value = "/list")
    public ResponseResult<List<User>> getList(@RequestBody User user) {
        return  ResponseResult.build(userService.getList(user),StatusCodeEnum.query_success);
    }

    @Operation(summary = "获取详情")
    @ApiOperationSupport(order = 6 ,author = "lw")
    @GetMapping(value = "/detail")
    public ResponseResult<User> getDetail(Long id){
        User user=userService.getById(id);
        user.setWxOpenid(null);
        return  ResponseResult.build(user,StatusCodeEnum.success);
    }

    @Operation(summary = "分页查询")
    @ApiOperationSupport(order = 7 ,author = "lw")
    @PostMapping(value = "/page")
    public ResponseResult<PageVo<User>> getPage(@RequestBody PageDto<User> pageDto) {
        return  ResponseResult.build(userService.getPage(pageDto),StatusCodeEnum.query_success);
    }

    @Operation(summary = "导出")
    @RequestAuthCheck(menuName = menuName,action = ConstantConfig.export)
    @ApiOperationSupport(order = 8,author = "lw")
    @PostMapping(value = "/export")
    public void export(@RequestBody PageDto<User> pageDto, HttpServletResponse response) {
        PageVo<User> pageVo=userService.getPage(pageDto);
        MyExcelUtil.export(response,pageVo,NormalUtil.mergeMaps(User.getExcelCols(), BaseEntity.getExcelCols()),User.entityTitle);
    }

    @Operation(summary = "导入")
    @RequestAuthCheck(menuName = menuName,action = ConstantConfig.Import)
    @ApiOperationSupport(order = 9,author = "lw")
    @PostMapping(value = "/import")
    public ResponseResult<List<User>>  importList(@RequestPart("file") MultipartFile file){
//       List<User> list=MyExcelUtil.readBig(file,User.class);
         List<User> list=MyExcelUtil.read(file,User.class);
//       try{
//           userService.saveBatch(list);
//       }catch (Exception e){
//           throw  new CustomException(StatusCodeEnum.import_error);
//       }
       return ResponseResult.build(list,StatusCodeEnum.import_success);
    }

    @Operation(summary = "获取登录图形验证码")
    @ApiOperationSupport(order = 10,author = "lw" )
    @GetMapping(value = "/getLoginPicCaptcha")
    public ResponseResult<PicCaptchaVo> getLoginPicCaptcha() {
        return  ResponseResult.build(userService.getPicCaptcha(),StatusCodeEnum.success);
    }

    @Operation(summary = "通过账号登录")
    @ApiOperationSupport(order = 11,author = "lw" )
    @PostMapping(value = "/loginByAccount")
    public ResponseResult<LoginVo> loginByAccount(@RequestBody LoginDto loginDto, HttpServletRequest request) {
        return  ResponseResult.build(userService.loginByAccount(loginDto,request),StatusCodeEnum.login_success);
    }

    @Operation(summary = "获取登录短信验证码")
    @ApiOperationSupport(order = 12,author = "lw" )
    @Parameters({
            @Parameter(name = "phone",description = "手机号码",required = true,in= ParameterIn.QUERY)
    })
    @GetMapping(value = "/getLoginShortMessageCaptcha")
    public ResponseResult<Boolean> getLoginShortMessageCaptcha(String phone) {
        return  ResponseResult.build(userService.getShortMessageCaptcha(phone),StatusCodeEnum.success);
    }

    @Operation(summary = "通过手机号登录")
    @ApiOperationSupport(order = 13,author = "lw" )
    @PostMapping(value = "/loginByPhone")
    public ResponseResult<LoginVo> loginByPhone(@RequestBody LoginDto loginDto, HttpServletRequest request) {
        return  ResponseResult.build(userService.loginByPhone(loginDto,null,request),StatusCodeEnum.login_success);
    }

    @Operation(summary = "获取生成微信登录授权二维码的所需参数")
    @ApiOperationSupport(order = 14,author = "lw" )
    @GetMapping(value = "/getWxQrCodeParams")
    public ResponseResult<WxQrCodeParamsVo> getWxQrCodeParams() {
        return  ResponseResult.build(new WxQrCodeParamsVo(ConstantConfig.webUrl,ConstantConfig.webAppid,StrUtil.uuid()),StatusCodeEnum.success);
    }

    @Operation(summary = "微信扫码登录")
    @ApiOperationSupport(order = 15,author = "lw" )
    @Parameters({
            @Parameter(name = "code",description = "扫码授权成功后得到的code",required = true,in= ParameterIn.QUERY)
    })
    @GetMapping(value = "/loginByWxScan")
    public ResponseResult<LoginVo> loginByWxScan(String code,HttpServletRequest request) {
        return  ResponseResult.build(userService.loginByWxScan(code,request),StatusCodeEnum.success);
    }

    @Operation(summary = "给系统用户绑定微信号并登录")
    @ApiOperationSupport(order = 16,author = "lw" )
    @PostMapping(value = "/wxBindToUserAndLogin")
    public ResponseResult<LoginVo> wxBindToUserAndLogin(LoginDto loginDto,HttpServletRequest request) {
        return  ResponseResult.build(userService.wxBindToUserAndLogin(loginDto,request),StatusCodeEnum.login_success);
    }

    @Operation(summary = "登出")
    @ApiOperationSupport(order = 17,author = "lw")
    @PostMapping(value = "/logout")
    public ResponseResult<Boolean> logout(@RequestHeader(name=ConstantConfig.tokenFieldName) String token) {
        userService.logout(token);
        return  ResponseResult.build(true,StatusCodeEnum.logout_success);
    }

    @Operation(summary = "头像上传")
    @ApiOperationSupport(order = 18,author = "lw")
    @PostMapping(value = "/uploadAvatar")
    public ResponseResult<String> uploadAvatar(@RequestPart("file") MultipartFile file) {
        //MinioFileUtil.upload(file,ConstantConfig.image);
        return  ResponseResult.build(LocalFileUtil.upload(file,ConstantConfig.image,resourceLoader),StatusCodeEnum.upload_success);
    }

    @Operation(summary = "头像删除")
    @ApiOperationSupport(order = 19,author = "lw")
    @PostMapping(value = "/deleteAvatar")
    public ResponseResult<Boolean> deleteAvatar(@RequestBody List<String> avatarUrls) {
        AtomicBoolean successAll= new AtomicBoolean(true);
        avatarUrls.forEach(v->{
            if(!LocalFileUtil.delete(LocalFileUtil.getFileNameByFullFileUrl(v),resourceLoader)) successAll.set(false);
        });
        //MinioFileUtil.remove(MinioFileUtil.getFileNameByFullFileUrl(url));
        return  ResponseResult.build(successAll.get(),StatusCodeEnum.success);
    }

    @Operation(summary = "获取当前登录用户信息")
    @ApiOperationSupport(order = 20 ,author = "lw")
    @PostMapping(value = "/getUserInfo")
    public ResponseResult<User> getUserInfo() {
        AuthContextUtil.IUser iUser=AuthContextUtil.get();
        iUser.setNameToMenuMap(null);
        NormalUtil.userInfoDesensitizedHandle(iUser);
        return  ResponseResult.build(iUser,StatusCodeEnum.success);
    }

    @Operation(summary = "角色分配")
    @ApiOperationSupport(order = 21,author = "lw")
    @RequestAuthCheck(menuName = menuName,action = ConstantConfig.giveAuth)
    @PostMapping(value = "/giveRoles")
    public ResponseResult<Boolean> giveRoles(@RequestBody GiveRolesDto giveRolesDto) {
        return  ResponseResult.build(userService.giveRoles(giveRolesDto),StatusCodeEnum.giveRoles_success);
    }

    @Operation(summary = "获取用户的角色信息")
    @ApiOperationSupport(order = 22 ,author = "lw")
    @GetMapping(value = "/getRolesInfo")
    public ResponseResult<List<Role>> getRolesInfo(@RequestParam(required = false,name = "userId") Long userId) {
        Long uid=AuthContextUtil.get().getId();
        if(userId!=null)  uid=userId;
        return  ResponseResult.build(userService.getRolesInfo(uid),StatusCodeEnum.success);
    }

    @Operation(summary = "获取用户的菜单信息")
    @ApiOperationSupport(order = 23,author = "lw" )
    @PostMapping(value = "/getMenusInfo")
    public ResponseResult<List<Menu>> getMenusInfo() {
        return  ResponseResult.build(userService.getMenusInfo(AuthContextUtil.get().getId()),StatusCodeEnum.success);
    }

    @Operation(summary = "大文件上传")
    @ApiOperationSupport(order = 24 ,author = "lw")
    @PostMapping(value = "/uploadBigFile")
    public ResponseResult<String> uploadBigFile(@RequestPart("file") MultipartFile file,@RequestParam("md5Hash") String md5Hash,@RequestParam("fileName") String fileName,
                                                @RequestParam("total") Integer total,@RequestParam("current") Integer current){
        String url=MinioFileUtil.uploadChunk(file,md5Hash,fileName,total,current);
        return  ResponseResult.build(url,StatusCodeEnum.upload_success);
    };

    @Operation(summary = "异步任务测试")
    @ApiOperationSupport(order = 25 ,author = "lw")
    @PostMapping(value = "/asyncTest")
    public ResponseResult<String> asyncTest(){
        String  res=null;

        CompletableFuture<String> resultFuture = testAsyncTaskService.executeAsyncTask();
        //resultFuture.cancel(true);  取消异步任务

        // 使用thenApply或thenAccept等方法处理异步结果
        resultFuture.thenAccept(result -> {
            //System.out.println("异步任务执行结果：" + result);
            // 对结果进行进一步处理...
        });

        // 如果需要阻塞等待结果并直接获取，可以使用get方法（不推荐在主线程中这样做）
        try {
            res=resultFuture.get();
            //System.out.println("异步任务执行结果（阻塞获取）：" + res);
        } catch (InterruptedException | ExecutionException e) {
            // 处理异常
            e.printStackTrace();
        }
        return  ResponseResult.build(res,StatusCodeEnum.success);
    };
}
